﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using Lucene.Net.Documents;
using TagLib;

namespace FortuneArterial.Site.Laboratory.Models
{
    public class MusicFileEntity
        : FileEntity
    {
        [DisplayName("标题")]
        public string Title { get; set; }
        [DisplayName("艺术家")]
        public string Artist { get; set; }
        [DisplayName("专辑")]
        public string Album { get; set; }
        [DisplayName("音轨")]
        public string Track { get; set; }
        [DisplayName("流派")]
        public string Genre { get; set; }
        [DisplayName("年代")]
        public string Year { get; set; }
        [DisplayName("备注")]
        public string Comment { get; set; }

        [DisplayName("频率")]
        public string SampleRate { get; set; }
        [DisplayName("码率")]
        public string Bitrate { get; set; }
        [DisplayName("长度")]
        public string Duration { get; set; }

        public MusicFileEntity()
            : base()
        {
        }

        public MusicFileEntity(string path)
            : base(path)
        {
            var file = TagLib.File.Create(path);

            this.Title = GetTagChinese(file.Tag.Title);
            this.Artist = GetTagChinese(file.Tag.FirstPerformer);
            this.Album = GetTagChinese(file.Tag.Album);
            this.Track = GetTagChinese(file.Tag.Track.ToString());
            this.Genre = GetTagChinese(file.Tag.FirstGenre);
            if (file.Tag.Year != 0)
                this.Year = GetTagChinese(file.Tag.Year.ToString());
            this.Comment = GetTagChinese(file.Tag.Comment);

            this.SampleRate = string.Format("{0} Hz", file.Properties.AudioSampleRate);
            this.Bitrate = string.Format("{0} Kbps", file.Properties.AudioBitrate);
            this.Duration = file.Properties.Duration.ToString("g");

            this.FileSize = file.Length;
        }

        private string GetTagChinese(string tag)
        {
            if (string.IsNullOrEmpty(tag)) return string.Empty;
            return Encoder.GetString(Decoder.GetBytes(tag));
        }

        private string[] GetTagChinese(string[] tags)
        {
            if (tags == null) return new string[] { };
            return tags.Select(GetTagChinese).ToArray();
        }

        public override Lucene.Net.Documents.Document ToDocument()
        {
            var doc = base.ToDocument();

            doc.Add(new Field("Title", this.Title, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Artist", this.Artist, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Album", this.Album, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Genre", this.Genre, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Year", this.Year, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Comment", this.Comment, Field.Store.YES, Field.Index.ANALYZED));

            doc.Add(new Field("SampleRate", this.SampleRate, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Bitrate", this.Bitrate, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Duration", this.Duration, Field.Store.YES, Field.Index.ANALYZED));

            return doc;
        }

        public override void FromDocument(Document doc)
        {
            base.FromDocument(doc);

            this.Title = doc.Get("Title");
            this.Artist = doc.Get("Artist");
            this.Album = doc.Get("Album");
            this.Track = doc.Get("Track");
            this.Genre = doc.Get("Genre");
            this.Year = doc.Get("Year");
            this.Comment = doc.Get("Comment");

            this.SampleRate = doc.Get("SampleRate");
            this.Bitrate = doc.Get("Bitrate");
            this.Duration = doc.Get("Duration");
        }

        public static Encoding Decoder = Encoding.GetEncoding("ISO-8859-1");
        public static Encoding Encoder = Encoding.UTF8;
    }
}